import type {Message, UIMessage} from 'ai';
import {useSWRConfig} from 'swr';
import {useCopyToClipboard} from 'usehooks-ts';

import {CopyIcon, ThumbDownIcon, ThumbUpIcon} from './icons';
import {Button} from '@/components/ui/button';
import {Tooltip, TooltipContent, TooltipProvider, TooltipTrigger} from '@/components/ui/tooltip';
import {memo} from 'react';
import equal from 'fast-deep-equal';
import {toast} from 'sonner';
import type {ChatMessageVote} from '@/types/interfaces';
import {useParams} from 'next/navigation';
import apiClient from "@/lib/axios";

export function PureMessageActions({
                                       chatId,
                                       message,
                                       vote,
                                       isLoading
                                   }: {
    chatId: string;
    message: Message;
    vote: ChatMessageVote | undefined;
    isLoading: boolean;
}) {
    const {mutate} = useSWRConfig();
    const [_, copyToClipboard] = useCopyToClipboard();
    const {projectId} = useParams();
    if (isLoading) return null;
    if (message.role === 'user') return null;
    return (
        <TooltipProvider delayDuration={0}>
            <div className="flex flex-row gap-2">
                <Tooltip>
                    <TooltipTrigger asChild>
                        <Button
                            className="py-1 px-2 h-fit text-muted-foreground"
                            variant="outline"
                            onClick={async () => {
                                const textFromParts = message.parts
                                    ?.filter(part => part.type === 'text')
                                    .map(part => part.text)
                                    .join('\n')
                                    .trim();

                                if (!textFromParts) {
                                    toast.error("There's no text to copy!");
                                    return;
                                }

                                await copyToClipboard(textFromParts);
                                toast.success('Copied to clipboard!');
                            }}
                        >
                            <CopyIcon/>
                        </Button>
                    </TooltipTrigger>
                    <TooltipContent>Copy</TooltipContent>
                </Tooltip>

                <Tooltip>
                    <TooltipTrigger asChild>
                        <Button
                            data-testid="message-upvote"
                            className="py-1 px-2 h-fit text-muted-foreground !pointer-events-auto"
                            disabled={vote?.isUpvote}
                            variant="outline"
                            onClick={async () => {
                                const upvote = apiClient.patch(`/${projectId}/chat/vote`, {
                                    chatId: chatId,
                                    messageId: message.id,
                                    type: 'up'
                                });

                                toast.promise(upvote, {
                                    loading: 'Upvoting Response...',
                                    success: () => {
                                        mutate<Array<ChatMessageVote>>(
                                            `/${projectId}/chat/vote?chatId=${chatId}`,
                                            currentVotes => {
                                                if (!currentVotes) return [];

                                                const votesWithoutCurrent = currentVotes.filter(
                                                    vote => vote.messageId !== message.id
                                                );

                                                return [
                                                    ...votesWithoutCurrent,
                                                    {
                                                        chatId,
                                                        messageId: message.id,
                                                        isUpvote: true
                                                    }
                                                ];
                                            },
                                            {revalidate: false}
                                        );

                                        return 'Upvoted Response!';
                                    },
                                    error: 'Failed to upvote response.'
                                });
                            }}
                        >
                            <ThumbUpIcon/>
                        </Button>
                    </TooltipTrigger>
                    <TooltipContent>Upvote Response</TooltipContent>
                </Tooltip>

                <Tooltip>
                    <TooltipTrigger asChild>
                        <Button
                            data-testid="message-downvote"
                            className="py-1 px-2 h-fit text-muted-foreground !pointer-events-auto"
                            variant="outline"
                            disabled={vote && !vote.isUpvote}
                            onClick={async () => {
                                const downvote = apiClient.patch(`/${projectId}/chat/vote`, {
                                    chatId,
                                    messageId: message.id,
                                    type: 'down'
                                });

                                toast.promise(downvote, {
                                    loading: 'Downvoting Response...',
                                    success: () => {
                                        mutate<Array<ChatMessageVote>>(
                                            `/${projectId}/chat/vote?chatId=${chatId}`,
                                            currentVotes => {
                                                if (!currentVotes) return [];

                                                const votesWithoutCurrent = currentVotes.filter(
                                                    vote => vote.messageId !== message.id
                                                );

                                                return [
                                                    ...votesWithoutCurrent,
                                                    {
                                                        chatId,
                                                        messageId: message.id,
                                                        isUpvote: false
                                                    }
                                                ];
                                            },
                                            {revalidate: false}
                                        );

                                        return 'Downvoted Response!';
                                    },
                                    error: 'Failed to downvote response.'
                                });
                            }}
                        >
                            <ThumbDownIcon/>
                        </Button>
                    </TooltipTrigger>
                    <TooltipContent>Downvote Response</TooltipContent>
                </Tooltip>
            </div>
        </TooltipProvider>
    );
}

export const MessageActions = memo(PureMessageActions, (prevProps, nextProps) => {
    if (!equal(prevProps.vote, nextProps.vote)) return false;
    if (prevProps.isLoading !== nextProps.isLoading) return false;

    return true;
});
